#include <iostream>
#include <cassert>
#include <vector>
#include <algorithm>
#include <sstream>
#include <list>
using namespace std;


struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
 
class Solution {
public:
// dp[i][j]表示str[1:i]和pattern[1:j]能否匹配，为0表示无法匹配，为1表示可以匹配
//
// 分析状态转移方程
//   对于dp[i][j]，如果str[i]与p[j]相同或者p[j]为.，则dp[i][j] = dp[i-1][j-1]，即与s[1:i-1]和p[1:j-1]的匹配情况相同
//   如果p[j]为*，则表示这个字符可以联合p[j-1]使用来匹配当前的s[i](这个选择可做可不做，但我们尽量去匹配字符串)
//   考虑p[j]为*，如果p前一个字符为.，显然可以用一次.*组合匹配到s[i]，如果p前一个字符p[j-1]不为.并且不与s[i]相同，则不能使用
//   综合考虑，若p[j]=='*'
//   1. 不选择替换，使用0次*，dp[i][j] = dp[i][j-2]
//   2. 当p[j-1]为.或者与s[i]相同时，可以使用一次替换，则dp[i][j] = dp[i-1][j]
//   两者求或 (因为我们尽可能去匹配字符串，所以只要有一种情况匹配成功，则匹配成功)
// 初始化主要考虑p去匹配一个空串的情况，和上面类似的分析过程即可得出结论
    bool isMatch(string s, string p) {
        if (p.empty()) return s.empty();
        vector<vector<int>> dp(s.size()+1, vector<int>(p.size()+1, 0)); dp[0][0] = 1;
        // 初始化dp[0][j]表示p[1:j]与空串的匹配情况
        for (int j = 1; j <= p.size(); j++) {
            if (p[j-1] != '*') continue;
            else dp[0][j] = dp[0][j-2];
        }
        for (int i = 1; i <= s.size(); i++) {
            for (int j = 1; j <= p.size(); j++) {
                if (s[i-1] == p[j-1] || p[j-1] == '.') dp[i][j] = dp[i-1][j-1];
                else if (p[j-1] == '*') {
                    dp[i][j] = dp[i][j-2]; 
                    if (p[j-2] == '.' || p[j-2] == s[i-1]) dp[i][j] = dp[i][j] || dp[i-1][j];
                }
            }
        }
        return dp[s.size()][p.size()];
    }
};



string stringToString(string input) {
    assert(input.length() >= 2);
    string result;
    for (int i = 1; i < input.length() -1; i++) {
        char currentChar = input[i];
        if (input[i] == '\\') {
            char nextChar = input[i+1];
            switch (nextChar) {
                case '\"': result.push_back('\"'); break;
                case '/' : result.push_back('/'); break;
                case '\\': result.push_back('\\'); break;
                case 'b' : result.push_back('\b'); break;
                case 'f' : result.push_back('\f'); break;
                case 'r' : result.push_back('\r'); break;
                case 'n' : result.push_back('\n'); break;
                case 't' : result.push_back('\t'); break;
                default: break;
            }
            i++;
        } else {
          result.push_back(currentChar);
        }
    }
    return result;
}

string boolToString(bool input) {
    return input ? "True" : "False";
}

int main() {
    string s,p;
    cin>>s;
    cin>>p;
    bool ret = Solution().isMatch(s, p);

    string out = boolToString(ret);
    cout << out << endl;
    return 0;
}